#define OS_Init_ProcSpec()      // Empty macro for PIC16






/**************************************************************************************************
 * 
 * MAKE FSR POINTER TO OS_CUR_TASK
 *
 * (for code reducing)
 *
 **************************************************************************************************/

#if defined(_ROMSIZE) && (_ROMSIZE <= 0x800)

    asm("   global __OS_SET_FSR_CUR_TASK        ");
    asm("   global __OS_SET_FSR_CUR_TASK_W      ");
    asm("__OS_SET_FSR_CUR_TASK:                 ");
    asm("       movlw       0                   ");
    asm("__OS_SET_FSR_CUR_TASK_W:               ");
    asm("       addwf       __OS_CurTask, w     ");
    asm("       movwf       __fsr               ");
    #if OS_BANK_TASKS >= 2
    asm("       bsf         __status, 7         ");
    #else
    asm("       bcf         __status, 7         ");
    #endif
    asm("       return                          ");

#endif




















/**************************************************************************************************
 * 
 * C O U N T I N G    S E M A P H O R E S
 *
 * (OS_ENABLE_CSEM must be defined in OSAcfg.h)
 *
 **************************************************************************************************/


#ifdef OS_ENABLE_CSEM


    /************************************************************************/
    /* Increase counting semaphore by  1                                    */
    /************************************************************************/

    //------------------------------------------------------------------------------
    #define _OS_SignalCSem_DEFINED
    //------------------------------------------------------------------------------
   
    void _OS_SignalCSem (OST_CSEM *pCSem)
    {
        __OS_CSEM_DI();
        OS_Flags.bEventError = 0;       // Semaphore overflow flag

        //------------------------------------------------------------------------------
        // For one-byte semaphores
        #if OS_CSEM_SIZE == 1
            _fsr = (_FSR_TYPE)pCSem;
            #ifdef __OSAPICC__
                _status &= 0x7F;        // IRP = 0
            #endif
            _indf++;
            if (!_indf)
            {
                _indf--;
                OS_Flags.bEventError = 1;   // Set error flag if overflow
            }

        //------------------------------------------------------------------------------
        // for two-bytes semaphores
        #elif OS_CSEM_SIZE == 2
            _fsr = (_FSR_TYPE)pCSem;
            _status &= 0x7F;        // IRP = 0
            asm("\t    movlw    1     ");
            asm("\t    addwf    __indf,f    ");
            asm("\t    incf     __fsr, f    ");
            asm("\t    btfsc    __status, 0     ");
            asm("\t    incf     __indf,f     ");
            asm("\t    movf     __indf, w     ");
            asm("\t    decf     __fsr, f     ");
            asm("\t    iorwf    __indf, w      ");
            if (ZERO) {
                asm("\t    movlw    -1     ");
                asm("\t    movwf    __indf     ");
                asm("\t    incf     __fsr,f     ");
                asm("\t    movwf    __indf     ");
                OS_Flags.bEventError = 1;   // Set error flag if overflow
            }
        //------------------------------------------------------------------------------
        // for four-bytes semaphores
        #else 
            (*pCSem)++;
            if (!*pCSem) {          
                (*pCSem) = -1;
                OS_Flags.bEventError = 1;   // Set error flag if overflow
            }
        #endif
        //------------------------------------------------------------------------------
        __OS_CSEM_RI();
    }



    //------------------------------------------------------------------------------
    #if defined(OS_ENABLE_INT_CSEM)
    //------------------------------------------------------------------------------
        #define _OS_IntSignalCSem_DEFINED
    
        void _OS_IntSignalCSem (OST_CSEM *pCSem)
        {
            OS_Flags.bEventError = 0;       // Semaphore overflow flag

            //------------------------------------------------------------------------------
            // For one-byte semaphores
            #if OS_CSEM_SIZE == 1
                _fsr = (_FSR_TYPE)pCSem;
                #ifdef __OSAPICC__
                    _status &= 0x7F;        // IRP = 0
                #endif
                _indf++;
                if (!_indf)
                {
                    _indf--;
                    OS_Flags.bEventError = 1;   // Set error flag if overflow
                }

            //------------------------------------------------------------------------------
            // for two-bytes semaphores
            #elif OS_CSEM_SIZE == 2
                _fsr = (_FSR_TYPE)pCSem;
                _status &= 0x7F;        // IRP = 0
                asm("\t    movlw    1     ");
                asm("\t    addwf    __indf,f    ");
                asm("\t    incf     __fsr, f    ");
                asm("\t    btfsc    __status, 0     ");
                asm("\t    incf     __indf,f     ");
                asm("\t    movf     __indf, w     ");
                asm("\t    decf     __fsr, f     ");
                asm("\t    iorwf    __indf, w      ");
                if (ZERO) {
                    asm("\t    movlw    -1     ");
                    asm("\t    movwf    __indf     ");
                    asm("\t    incf     __fsr,f     ");
                    asm("\t    movwf    __indf     ");
                    OS_Flags.bEventError = 1;   // Set error flag if overflow
                }
            //------------------------------------------------------------------------------
            // for four-bytes semaphores
            #else 
                (*pCSem)++;
                if (!*pCSem) {          
                    (*pCSem) = -1;
                    OS_Flags.bEventError = 1;   // Set error flag if overflow
                }
            #endif
            //------------------------------------------------------------------------------
        }

    #endif



//------------------------------------------------------------------------------
#endif  // OS_ENABLE_CSEM
//------------------------------------------------------------------------------
    







/****************************************************************************************************
 * 
 * D I S A B L E   I N T E R R U P T S   W I T H    S A V I N G   G I E
 * 
 * char OS_DI (void)   
 *
 ****************************************************************************************************/

#define OS_DI_DEFINED

asm("   global _OS_DI           ");
asm("_OS_DI:                    ");
asm("   clrf    __status        ");
asm("   movf    __intcon, w      ");
asm("   andlw   0x80            ");
asm("_DI_REPEAT:                ");
asm("   bcf     __intcon, 7      ");
asm("   btfss   __intcon, 7      ");
asm("   return                  ");
asm("   goto    _DI_REPEAT      ");









 
    
    
/****************************************************************************************************
 * 
 * C R I T I C A L   S E C T I O N S   W O R K 
 *
 ****************************************************************************************************/
//------------------------------------------------------------------------------
#ifdef OS_ENABLE_CRITICAL_SECTION
//------------------------------------------------------------------------------
    
/************************************************************************/
/* Enter critical section                                               */
/************************************************************************/
#define OS_EnterCriticalSection_DEFINED

void OS_EnterCriticalSection (void)
{
    _OST_INT_TYPE temp;
    temp = OS_DI();
    OS_Flags.bInCriticalSection = 1; 

    OS_Flags.bGIE_CTemp = 0;
    if (temp & 0x80) OS_Flags.bGIE_CTemp = 1;

}

/************************************************************************/
/* Leave critical section                                               */
/************************************************************************/
#define OS_LeaveCriticalSection_DEFINED

void OS_LeaveCriticalSection (void)
{
    char temp;
    OS_Flags.bInCriticalSection = 0; 
    temp = 0;
    if (OS_Flags.bGIE_CTemp) temp |= 0x80;
    OS_RI(temp);
}

//------------------------------------------------------------------------------
#endif      //     #ifdef OS_ENABLE_CRITICAL_SECTION
//------------------------------------------------------------------------------


















//------------------------------------------------------------------------------
#ifdef OS_ENABLE_TTIMERS

/****************************************************************************************************
 * 
 *  D E L A Y S   W O R K 
 *
 ****************************************************************************************************/
/************************************************************************/
/*                                                                      */
/* Init task timer for counting                                         */
/* (internal system function)                                           */
/*                                                                      */
/************************************************************************/
#define _OS_InitDelay_DEFINED


void _OS_InitDelay (_OST_TTIMER Delay)
{

    _OS_SET_FSR_CUR_TASK();
    _OS_bTaskCanContinue = 0;
    _OS_bTaskDelay = 0;         // Clear bDelay to prevent timer changing in interrupt

    if (Delay)
    {

        Delay ^= -1;
        Delay ++;
        _OS_CurTask->Timer = Delay;
        
        _OS_SET_FSR_CUR_TASK();
        _OS_bTaskDelay = 1;
        _OS_bTaskReady = 1;

    }
}

//______________________________________________________________________________
//******************************************************************************

#endif  // #ifdef OS_TIMER



    










    
    
    
    
    

    








/****************************************************************************************************
 * 
 * 
 *  T A S K   W O R K   F U N C T I O N S
 *  
 *
 ****************************************************************************************************/


/************************************************************************/
/*                                                                      */
/* Create task in any free descriptor                                   */
/* On return:                                                           */
/*      =1 - OK,                                                        */
/*      =0 - there is no free descriptor                                */
/*                                                                      */
/************************************************************************/

//______________________________________________________________________________
////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------
#define _OS_CreateTask_DEFINED

bit _OS_CreateTask(_OST_INT_TYPE priority, OST_CODE_POINTER TaskAddr)
{
    OST_TASK_POINTER Task;
    
    OS_Flags.bError = 0;

    #if defined(OS_DISABLE_PRIORITY)
    priority = 0;
    #endif

    Task = (OST_TASK_POINTER)OS_TaskVars;
    _OS_temp = OS_TASKS;
    do {
        if (!Task->State.bEnable)
        {
            ((OST_TASK_STATE*)&priority)->bEnable = 1;
            ((OST_TASK_STATE*)&priority)->bReady = 1;
            

            Task->pTaskPointer = TaskAddr;
            #ifdef OS_ENABLE_TTIMERS
                Task->Timer = 0;
            #endif
            *((OS_TASKS_BANK char*)&Task->State) = priority;
            // Now FSR points to task descriptor      
            OS_Flags.bError = 0;
            return 1;
        
        }
        Task ++;
    } while (_OS_temp--);
    
    // No free descriptor
    OS_Flags.bError = 1;
    return 0;
}

































/******************************************************************************************
 *
 *  P T I M E R S   W O R K  
 *
 ******************************************************************************************/
#ifdef OS_ENABLE_DTIMERS

/************************************************************************/
/*                                                                      */
/************************************************************************/
//------------------------------------------------------------------------------
#define _OS_CreateDTimer_DEFINED
//------------------------------------------------------------------------------

void _OS_CreateDTimer (OST_DTIMER *dtimer)
{
    _OS_temp = OS_DI();
    
    IRP = 0;
    _fsr = (_FSR_TYPE) dtimer;
    _indf = *((OS_BANK char*)&_OS_DTimers.Flags); 
    // Here: bActive is set,
    //       bTimeout is cleared,
    //       bRun is cleared
    //       bNextEnable is copied

    _fsr++;
    _indf = (_FSR_TYPE)_OS_DTimers.Next;

    _fsr++;
    _indf = 0;
    _fsr++;
    #if  OS_DTIMER_SIZE >= 2
        _indf = 0;
        _fsr++;
    #endif
    #if  OS_DTIMER_SIZE == 4
        _indf = 0;
        _fsr++;
        _indf = 0;
    #endif


    _OS_DTimers.Next = (OST_DTIMER*)dtimer;
    _OS_DTimers.Flags.bNextEnable = 1;
    
    #if !defined(__OSAPICC12__)
    OS_RI(_OS_temp);
    #endif
}





/************************************************************************/
/*                                                                      */
/************************************************************************/
//------------------------------------------------------------------------------
#define _OS_DeleteDTimer_DEFINED
//------------------------------------------------------------------------------
void _OS_DeleteDTimer (OST_DTIMER *dtimer)
{

    OST_DTIMER *ptcb;
    char flags;

    IRP = 0;
    _fsr = ((_FSR_TYPE)dtimer);
    flags = _indf;
    _OS_ClearIndfTimerActive;
    _fsr++;
    ptcb = (OST_DTIMER *)_indf;
    _fsr = (_FSR_TYPE)&_OS_DTimers;
    // Search timer in list of active timers
REPEAT:
    if (_OS_CheckIndfTimerNextEnable)   // exit if timer not found
    {
        _fsr++;
        if ((_FSR_TYPE)_indf == (_FSR_TYPE)dtimer)  // Check pointer to next timer 
        {
            _OS_temp = OS_DI();         // Disable interrupts
            _indf = *((char*)&ptcb);    // Change pointer
            _fsr--;                     
            // Clear NextEnable flag if it was last timer
            if (!((OST_DTIMER_FLAGS*)&flags)->bNextEnable) _OS_ClearIndfTimerNextEnable;
            OS_RI(_OS_temp);
            return;
        }
        _fsr = (_FSR_TYPE)_indf;
        goto REPEAT;
    }
        
}



#endif  //  OS_ENABLE_DTIMERS


























/****************************************************************************************************
 * 
 * C H E C K   E V E N T   A N D   S E T / C L E A R   R E A D Y   F L A G 
 *
 * (internal system function) 
 *
 ****************************************************************************************************/



//------------------------------------------------------------------------------
#define _OS_CheckEvent_DEFINED
//------------------------------------------------------------------------------
bit _OS_CheckEvent (char bEvent)
{



    OS_Flags.bTimeout = 0;
    _OS_SET_FSR_CUR_TASK();
    CARRY = 0;
    if (bEvent) {
        if (_OS_bTaskReady) {
#if defined(OS_ENABLE_TTIMERS)
    EXIT_OK:
#endif
            CARRY = 1;
        }
        _OS_bTaskReady = 1;
        #if defined(OS_ENABLE_TTIMERS)
            if (CARRY) _OS_bTaskDelay = 0;
        #endif
        asm("   return     ");
    }
    _OS_bTaskReady = 0;
    #if defined(OS_ENABLE_TTIMERS)
        asm("   btfss   __indf, 4     ");
        asm("   btfss   __indf, 5     ");
        asm("   return                ");
        OS_Flags.bTimeout = 1;
        goto EXIT_OK;
    #else
        asm("   return  ");
    #endif

}


